package com.mirabelle.juice.controller;

import java.io.Serializable;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.mirabelle.juice.model.Author;
import com.mirabelle.juice.model.Collection;
import com.mirabelle.juice.service.AuthorService;
import com.mirabelle.juice.service.CollectionService;

@Controller("C_AUTHOR")
@Scope("session")
public class CAuthor implements Serializable {
	private static final long serialVersionUID = 1L;
	private transient Logger log = LoggerFactory.getLogger(getClass());

	private String firstName = null;
	private String lastName = null;
	private String nickName = null;
	private String mail1 = null;
	private String mail2 = null;
	private String password1 = null;
	private String password2 = null;
	private boolean admin = false;
	private String comment = null;

	Author currentAuthor = null;

	@Autowired
	@Qualifier("AuthorService")
	protected AuthorService authorService;
	@Autowired
	@Qualifier("CollectionService")
	protected CollectionService collectionService;
	@Autowired
	@Qualifier("C_LOGGED_AUTHOR")
	private CPreferences authorPreferences;
	

	@PostConstruct
	public void init() {
		log.debug("Initialisation du controlleur C_AUTHOR.");
	}
	
	public String register() {
		log.debug("Appel de la methode register");
		boolean isOk = true;
		if (!password1.equals(password2)) {
			log.error("Les mots de passe ne sont pas identiques");
			FacesContext.getCurrentInstance().addMessage(
					"register_form:input_password1",
					new FacesMessage(FacesMessage.SEVERITY_WARN, null,
							"Les mots de passe ne sont pas identiques"));
			FacesContext.getCurrentInstance().addMessage(
					"register_form:input_password2",
					new FacesMessage(FacesMessage.SEVERITY_WARN, null,
							"Les mots de passe ne sont pas identiques"));
			isOk = false;
		} 
		if (!mail1.equals(mail2)) {
			log.error("Les mails ne sont pas identiques");
			FacesContext.getCurrentInstance().addMessage(
					"register_form:input_mail1",
					new FacesMessage(FacesMessage.SEVERITY_WARN, null,
							"Les adresses mail ne sont pas identiques"));
			FacesContext.getCurrentInstance().addMessage(
					"register_form:input_mail2",
					new FacesMessage(FacesMessage.SEVERITY_WARN, null,
							"Les adresses mail ne sont pas identiques"));
			isOk = false;
		} 
		if (checkIfExistByMail()) {
			log.error("Ce mail existe deja");
			FacesContext.getCurrentInstance().addMessage(
					"register_form:input_mail1",
					new FacesMessage(FacesMessage.SEVERITY_ERROR, null,
							"Cette adresse est déjà utilisée"));
			isOk = false;
		}
		if (checkIfExistByNickName()) {
			log.error("Ce pseudo existe deja");
			FacesContext.getCurrentInstance().addMessage(
					"register_form:input_nickname",
					new FacesMessage(FacesMessage.SEVERITY_ERROR, null,
							"Ce pseudo est déjà utilisé"));
			isOk = false;
		}
		if (isOk) {
			log.debug("Création du compte");
			Author author = new Author();
			author.setFirstName(firstName);
			author.setLastName(lastName);
			author.setNickName(nickName);
			author.setMail(mail1);
			author.setPassword(encodeMD5(password1));
			author.setCreated(new java.util.Date());
			author.setModified(null);
			author.setAdmin(admin);
			author.setComment(comment);
			log.debug("Création du compte pour l'auteur: " + author);
			currentAuthor = authorService.register(author);
			Collection c = new Collection();
			c.setAuthor(currentAuthor);
			c.setName("Collection de " + currentAuthor.getNickName());
			c.setComment("Collection par defaut créee à la créeation du compte. ");
			c.setCreated(new Date());
			c.setModified(new Date());
			currentAuthor.getCollections().add(c);
			log.debug("Création de la collection associée");
			collectionService.saveCollection(c);
			return "registered";
		}
		return null;
	}

	public void update(ActionEvent e) {
		log.debug("Appel de l'action update");
		if (!password1.equals(password2)) {
			log.debug("Les mots de passe ne sont pas identiques");
			FacesContext.getCurrentInstance().addMessage(
					"input_password1",
					new FacesMessage(FacesMessage.SEVERITY_WARN, null,
							"Les mots de passe ne sont pas identiques"));
		} else {
			log.debug("Mise à jour du mot de passe pour l'utilisateur " + authorPreferences.getLoggedAuthor());
			Author author = authorPreferences.getLoggedAuthor();
			author.setPassword(encodeMD5(password1));
			authorService.register(author);
		}
	}

	private boolean checkIfExistByMail() {
		if (null != authorService.findAuthorByMail(mail1)) {
			return true;
		}
		return false;
	}
	
	private boolean checkIfExistByNickName() {
		if (null != authorService.findAuthorByNickName(nickName)) {
			return true;
		}
		return false;
	}
	
	private String encodeMD5(String text) {
		log.debug("Encodage md5 de la chaine: " + text);
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			log.error("", e);
		}
		messageDigest.reset();
		messageDigest.update(text.getBytes(Charset.forName("UTF8")));
		byte[] resultByte = messageDigest.digest();
		String encoded = new String(Hex.encodeHex(resultByte));
		log.debug("Chaine encodée: " + encoded);
		return encoded;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	public String getNickName() {
		return nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	public String getMail1() {
		return mail1;
	}

	public void setMail1(String mail1) {
		this.mail1 = mail1;
	}

	public String getMail2() {
		return mail2;
	}

	public void setMail2(String mail2) {
		this.mail2 = mail2;
	}

	public String getPassword1() {
		return password1;
	}

	public void setPassword1(String password1) {
		this.password1 = password1;
	}

	public String getPassword2() {
		return password2;
	}

	public void setPassword2(String password2) {
		this.password2 = password2;
	}

	public boolean isAdmin() {
		return admin;
	}

	public void setAdmin(boolean admin) {
		this.admin = admin;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public Author getCurrentAuthor() {
		return currentAuthor;
	}

	public void setCurrentAuthor(Author currentAuthor) {
		this.currentAuthor = currentAuthor;
	}

	public CPreferences getauthorPreferences() {
		return authorPreferences;
	}
	
}
